// -----------------------------------------------------------------------
//  <copyright file="CreateRoleResourceCommand.cs" company="LiuliuSoft">
//      Copyright (c) 2022-2025 DaprPlus. All rights reserved.
//  </copyright>
//  <site>https://dapr.plus</site>
//  <last-editor>郭明锋</last-editor>
//  <last-date>2025/1/8 18:17</last-date>
// -----------------------------------------------------------------------

using DaprPlus.Authorization.Domain;
using DaprPlus.Authorization.Domain.Entities;
using DaprPlus.Authorization.Domain.Specs;


namespace DaprPlus.Authorization.Application.Commands;

[AuthConfig(typeof(RoleResource), ResourceAccessType.RoleLimit, "Set")]
public class SetRoleResourceCommand : IRequest<ApiResult>, ICommand
{
    /// <summary>
    /// 角色ID
    /// </summary>
    public long RoleId { get; set; }

    /// <summary>
    /// 角色资源数据集合
    /// </summary>
    public RoleResourceInDto[] Dtos { get; set; } = [];
}

public class SetRoleResourceCommandHandler(IServiceProvider serviceProvider)
    : IRequestHandler<SetRoleResourceCommand, ApiResult>
{
    public async Task<ApiResult> Handle(SetRoleResourceCommand request, CancellationToken cancellationToken)
    {
        // 从serviceProvider获取依赖项

        // 获取角色ID
        var roleId = request.RoleId;
        if (roleId == 0)
        {
            return ApiResult.Error("角色ID不能为空");
        }

        var repository = serviceProvider.GetRequiredService<IRepository<Resource>>();
        // 验证资源ID不重复
        var resourceIds = request.Dtos.Select(x => new { x.ResourceId }).ToList();
        if (resourceIds.Count != resourceIds.Distinct().Count())
        {
            return ApiResult.Error("批量设置的角色资源中存在重复的资源");
        }

        // 获取该角色当前的所有资源权限
        var roleResourceSpec = new ResourceIncludeRoleResourceSpec();
        var existingResources = await repository.GetAllAsync(roleResourceSpec, cancellationToken);
        var existingRoleResources = existingResources
            .SelectMany(r => r.RoleResources)
            .Where(rr => rr.RoleId == roleId)
            .ToList();

        // 提取当前请求中的资源ID集合
        var requestResourceIds = request.Dtos.Select(dto => dto.ResourceId).ToHashSet();

        // 找出需要删除的角色资源
        var toRemove = existingRoleResources
            .Where(rr => !requestResourceIds.Contains(rr.ResourceId))
            .ToList();

        // 处理删除操作
        var service = serviceProvider.GetRequiredService<IResourceService>();
        var results = new List<ApiResult>();
        var result = await service.RemoveRoleResourceAsync(roleId, [.. toRemove.Select(x => x.ResourceId)], cancellationToken);
        results.Add(result);

        // 处理新增和更新操作
        result = await service.SetRoleResourceAsync(roleId, request.Dtos, cancellationToken);
        results.Add(result);
        if (results.Count == 0)
        {
            return ApiResult.Success("角色资源权限没有变化");
        }

        if (results.All(r => r.IsSuccess() || r.IsInfo()))
        {
            return ApiResult.Success("角色资源权限设置成功");
        }

        if (results.All(r => r.ResultType == ApiResultType.Info))
        {
            return ApiResult.Info("角色权限没有变化");
        }

        var errors = results.Where(r => r.IsError()).Select(r => r.Message);
        return ApiResult.Error($"部分角色资源权限设置失败：{string.Join(", ", errors)}");
    }
}

